package org.jiucheng.magpiebridge.transfer.aio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.jiucheng.magpiebridge.client.aio.ClientAttachment;
import org.jiucheng.magpiebridge.protocol.Message;

/**
 * 
 * @author jiucheng
 *
 */
public class TransferAttachment {
	// 当前在写
	public final AtomicBoolean writed = new AtomicBoolean(false);

	private AsynchronousSocketChannel client;
	private ByteBuffer writeByteBuffer;
	private ByteBuffer readByteBuffer;
	private int uri;

	private SocketChannel realSocketChannel;
	private boolean failed;
	
	private ClientAttachment clientAttachment;
	
	public ClientAttachment getClientAttachment() {
		return clientAttachment;
	}
	
	public TransferAttachment setClientAttachment(ClientAttachment clientAttachment) {
		this.clientAttachment = clientAttachment;
		return this;
	}
	
	public boolean isFailed() {
		return failed;
	}
	
	public TransferAttachment setFailed(boolean failed) {
		this.failed = failed;
		return this;
	}

	public SocketChannel getRealSocketChannel() {
		return realSocketChannel;
	}

	public TransferAttachment setRealSocketChannel(SocketChannel realSocketChannel) {
		this.realSocketChannel = realSocketChannel;
		return this;
	}

	public int getUri() {
		return uri;
	}

	public TransferAttachment setUri(int uri) {
		this.uri = uri;
		return this;
	}

	public AsynchronousSocketChannel getClient() {
		return client;
	}

	public TransferAttachment setClient(AsynchronousSocketChannel client) {
		this.client = client;
		return this;
	}

	public ByteBuffer getWriteByteBuffer() {
		return writeByteBuffer;
	}

	public TransferAttachment setWriteByteBuffer(ByteBuffer writeByteBuffer) {
		this.writeByteBuffer = writeByteBuffer;
		return this;
	}

	public ByteBuffer getReadByteBuffer() {
		return readByteBuffer;
	}

	public TransferAttachment setReadByteBuffer(ByteBuffer readByteBuffer) {
		this.readByteBuffer = readByteBuffer;
		return this;
	}

	public boolean canReaded() {
		while (!writed.compareAndSet(false, false)) {
			try {
				TimeUnit.MILLISECONDS.sleep(50L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	public boolean canWrited() {
		while (!writed.compareAndSet(false, true)) {
			try {
				TimeUnit.MILLISECONDS.sleep(50L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	public void close() {
		if (clientAttachment != null) {
			clientAttachment.getTransferAttachments().remove(getUri());
			clientAttachment = null;
		}
		if (realSocketChannel != null) {
			try {
				realSocketChannel.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			realSocketChannel = null;
		}
		if (client != null) {
			try {
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			client = null;
		}
	}
	
    // 代理连接断开消息发送
    public void disconnect() {
        Message message = new Message();
        message.setMagic(Message.MAGIC);
        message.setType(Message.Type.DISCONNECT);
        message.setUri(getUri());
        ByteBuffer writeByteBuffer = Message.toByteBuffer(message);
        if (canWrited()) {
        	getClient().write(writeByteBuffer, setWriteByteBuffer(writeByteBuffer).setFailed(true), new TransferWriteCompletionHandler());
        }
    }
}
